//==============================================================================
// Copyright (c) 2008-2013 Niall Ryan. All Rights Reserved.
//==============================================================================

#ifndef HYDRA_THREAD_INTERNAL_H
#define HYDRA_THREAD_INTERNAL_H 1

#include <windows.h>
#include <process.h>

namespace Hydra
{
	namespace Internal
	{
		class ThreadInvokerBase
		{
		public:
			virtual void Invoke() = 0;
		};

		template<typename F>
		class ThreadInvoker0 : public ThreadInvokerBase
		{
		public:
			ThreadInvoker0(F function) : m_function(function) { }
			virtual void Invoke()	{ m_function(); }
		private:
			F m_function;
		};

		template<typename F, typename X>
		class ThreadInvoker1 : public ThreadInvokerBase
		{
		public:
			ThreadInvoker1(F function, X x) : m_function(function), m_x(x) { }
			virtual void Invoke()	{ m_function(m_x); }
		private:
			F m_function;
			X m_x;
		};

		template<typename F, typename X, typename Y>
		class ThreadInvoker2 : public ThreadInvokerBase
		{
		public:
			ThreadInvoker2(F function, X x, Y y) : m_function(function), m_x(x), m_y(y) { }
			virtual void Invoke()	{ m_function(m_x, m_y); }
		private:
			F m_function;
			X m_x;
			Y m_y;
		};

		inline unsigned int threadGetId()
		{
			return GetCurrentThreadId();
		}

		inline void threadSleep(unsigned int duration)
		{
			Sleep(duration);
		}

		inline void threadYield()
		{
			SwitchToThread();
		}

		inline void threadPause(int loops)
		{
			__asm
			{
				mov eax, loops
			loop1:
				pause
				sub eax,1
				jnz loop1
			}
		}
	}
}

#endif
